//
//  AVFoundationr+AVAsset.swift
//  SwiftCode
//
//  Created by yuhus on 2023/9/21.
//  https://developer.apple.com/documentation/avfoundation/media_assets/loading_media_data_asynchronously

import Foundation
import AVFoundation

extension AVFoundationExample {
  /// AVFoundation 使用 AVAsset 类来建模定时视听媒体。
  func loadAsyncProperty() {
    guard let url : URL = URL(string: self.urls[0]) else { return }
    
    let options = [AVURLAssetAllowsCellularAccessKey: false] // 允许蜂窝网络连接
    let asset: AVAsset = AVURLAsset(url: url, options: options) // or AVAsset(url: url)
    Timber.d(asset)
    
    if #available(iOS 15, *) {
      DispatchQueue.global().async { [weak self] in
        guard let self else { return }
        Task { try await self.loadMediaData(asset) }
      }
    } else {
      DispatchQueue.global().async {
        let duration = asset.duration
        let metadata = asset.metadata
        Timber.d(duration)
        Timber.d(metadata)
      }
    }
  }
  
  @available(iOS 15, *)
  private func loadMediaData(_ asset: AVAsset) async throws {
    // // A CMTime value and an array of AVMetadataItem.
    let (duration, metadata) = try await asset.load(.duration, .metadata)
    Timber.d(duration)
    Timber.d(metadata)
    
    // 确定元数据属性的加载状态。
    switch asset.status(of: .metadata) {
    case .notYetLoaded:
      Timber.d("The initial state of a property.")
    case .loading:
      Timber.d("The asset is actively loading the property value.")
    case .loaded:
      Timber.d("The property is ready to use.")
    case .failed(let error):
      Timber.d("The property value fails to load.", error)
    }
    
    // 验证元数据属性是否处于已加载状态。
    if case .loaded(let metadata) = asset.status(of: .metadata) {
      // Process the loaded value.
      processMetadata(metadata)
    }
    
    // 异步加载资源的音轨。
    let audioTracks = try await asset.loadTracks(withMediaType: .audio)
    var allDescriptions = [CMFormatDescription]()
    for track in audioTracks {
      // 异步加载每个音轨的格式描述。
      allDescriptions.append(contentsOf: try await track.load(.formatDescriptions))
    }
    // 收集独特的采样率，并将其从最高到最低排序。
    let sampleRates = Set(allDescriptions).map {
      Float($0.audioStreamBasicDescription?.mSampleRate ?? 0)
    }.sorted(by: { $0 > $1 })
    
    Timber.d(allDescriptions)
    Timber.d(sampleRates)
  }
  
  private func processMetadata(_ metadata: [AVMetadataItem]) {
    
  }
}
